package com.bawei.product.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

// 创建多线程配置类并实现 AsyncConfigurer
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    // ThreadPoolTaskExecutor是Spring提供的一个封装了java.util.concurrent.ThreadPoolExecutor的Bean，
    // 它更符合Spring框架的使用习惯，所以我们使用它来创建线程池。
    // 当池子里的线程处于空闲状态时，超过核心线程数（corePoolSize）的部分，如果时间超过keepAliveTime，就会被销毁
    // 即使池子中的线程数大于corePoolSize，如果队列workQueue未满，也会将新请求加入队列中，不会创建新的线程
    // 如果workQueue也满了，而且当前线程数小于maximumPoolSize，才会创建新的线程处理请求
    // 如果当前线程数达到了maximumPoolSize，那么就会按照RejectedExecutionHandler的策略来处理无法执行的新请求
    @Bean(destroyMethod="shutdown")  // 配置Bean的销毁方法
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数：线程池创建的时候初始化的线程数
        executor.setCorePoolSize(10);
        // 最大线程数：线程池最大的线程数
        executor.setMaxPoolSize(20);
        // 缓冲队列：用来缓冲执行任务的队列，这里设置为和最大线程数相同，保证队列不会满
        executor.setQueueCapacity(20);
        // 线程池关闭：等待所有任务都完成再关闭
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 等待时间：等待5秒后强制停止执行任务，这里设置为0，即不等待，直接强制执行任务
        executor.setAwaitTerminationSeconds(0);
        // 允许空闲时间：超过核心线程之外的线程到达60秒后会被销毁，这里设置为60秒
        executor.setKeepAliveSeconds(60);
        // 线程名称前缀
        executor.setThreadNamePrefix("learn-Async-");
        //拒绝策略：这里使用CallerRunsPolicy，表示如果队列满了，那么调用者线程会直接执行这个任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        // 初始化线程池
        executor.initialize();
        return executor;
    }}